object TestMatchCase {
  /** Scala中的模式匹配类似于Java中的switch语法 */
  def main(args: Array[String]): Unit = {
    /**
     * 模式匹配语法中，采用match关键字声明，每个分支采用case关键字进行声明，
     * （1）如果所有case都不匹配，那么会执行case _ 分支，类似于Java中default语句，若此时没有case _ 分支，那么会抛出MatchError。
     * （2）每个case中，不需要使用break语句，自动中断case。
     * （3）match case 语句可以匹配任何类型，而不只是字面量。
     * （4）=> 后面的代码块，直到下一个case语句之前的代码是作为一个整体执行，可以使用 {} 括起来，也可以不括。
     * */

    var a: Int = 10
    var b: Int = 20
    var operator: Char = 'd'

    var result = operator match {
      case '+' => a + b
      case '-' => a - b
      case '*' => a * b
      case '/' => a / b
      case _ => "illegal"
    }
    println(result)

    /**
     * v8.2 模式守卫
     * 1）说明
     * 如果想要表达匹配某个范围的数据，就需要在模式匹配中增加条件守卫。
     * */
    def abs(x: Int) = x match {
      case i: Int if i >= 0 => i
      case j: Int if j < 0 => -j
      case _ => "type illegal"
    }

    println(abs(-5))

    println(describe('+'))
    //泛型擦除
    println(describe1(List(1, 2, 3, 4, 5)))

    //数组例外，可保留泛型
    println(describe1(Array(1, 2, 3, 4, 5, 6)))
    println(describe1(Array("abc")))

    /**
     * scala模式匹配可以对集合进行精确的匹配，例如匹配只有两个元素的、且第一个元素为0的数组。
     * */
    for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))) { // 对一个数组集合进行遍历

      val result = arr match {
        case Array(0) => "0" //匹配Array(0) 这个数组
        case Array(x, y) => x + "," + y //匹配有两个元素的数组，然后将将元素值赋给对应的x, y
        case Array(0, _*) => "以0开头的数组" //匹配以0开头和数组
        case _ => "something else"
      }

      println("result = " + result)
    }

    // Scala 中，模式匹配可以匹配所有的字面量，包括字符串，字符，数字，布尔值等等。
    def describe(x: Any) = x match {
      case 5 => "Int five"
      case "hello" => "String hello"
      case true => "Boolean true"
      case '+' => "Char +"
    }

    // 需要进行类型判断时，可以使用前文所学的isInstanceOf[T]和asInstanceOf[T]，也可使用模式匹配实现同样的功能。
    def describe1(x: Any) = x match {

      case i: Int => "Int"
      case s: String => "String hello"
      case m: List[_] => "List"
      case c: Array[Int] => "Array[Int]"
      case someThing => "something else " + someThing
    }
  }
}
